package timeticker

import (
	"container/list"
	"fmt"
	"time"
)

type Task struct {
	interval time.Duration        //当前任务延迟多长时间后执行
	job      func(...interface{}) //回调函数（任务的具体执行方法）
	isCycle  bool                 //任务是否只执行一次（true，执行一次后就会从执行队列中清除掉
}

// TimeTicker 定时器类型
type TimeTicker struct {
	interval  time.Duration //定时器间隔多长时间执行一次
	ticker    *time.Ticker
	taskQueue *list.List
	closeChan chan bool //向此通道中输入true值，则会关闭此定时器
}

func New(interval time.Duration) *TimeTicker {
	if interval <= 0 {
		return nil
	}
	tt := &TimeTicker{
		interval:  interval,
		taskQueue: list.New(),
		closeChan: make(chan bool),
	}
	return tt
}

// AddTask 向定时器的任务队列中增加任务
//参数：task--增加的任务
//            isCycle--是否循环执行， true，每次执行完后依然保留在任务队列中，false，执行完一次后就会被清除掉
//考虑增加一组任务的方法
func (tt *TimeTicker) AddTask(task Task, isCycle bool) {
	tt.taskQueue.PushBack(task)
}

func (tt *TimeTicker) AddTaskList(task Task, isCycle bool) {

}

// AddJob 增加一个执行任务    参数：job--具体执行的函数
//         isCycle--是否循环执行，true:循环执行，每个周期均执行一次，    false:只执行一次，然后从任务队列中清除
func (tt *TimeTicker) AddJob(job func(...interface{}), isCycle bool) *list.Element {
	task := &Task{
		interval: 0,
		job:      job,
		isCycle:  isCycle,
	}
	e := tt.taskQueue.PushBack(task)
	return e
}

func (tt *TimeTicker) RemoveTask(e *list.Element) {
	tt.taskQueue.Remove(e)
	//fmt.Println(tt.taskQueue.Len())
}

func (tt *TimeTicker) Stop() {
	tt.ticker.Stop()
	tt.closeChan <- true
}

// Start 启动定时器，如果不传参数表示立刻启动，否则delay时间后启动
func (tt *TimeTicker) Start(delay ...time.Duration) {

	if len(delay) > 0 { //延迟delay[0]时间后启动

	} else { //立刻启动
		tt.ticker = time.NewTicker(tt.interval)
		tt.executeTaskQueue()
		for {
			select {
			case <-tt.ticker.C:
				tt.executeTaskQueue()
			case <-tt.closeChan:
				return
			}
		}

	}
}

func (tt *TimeTicker) executeTaskQueue() {

	if tt.taskQueue.Len() == 0 {
		fmt.Println("任务队列为空，没有可执行的任务......")
		return
	}

	for iter := tt.taskQueue.Front(); iter != nil; iter = iter.Next() {
		t := iter.Value
		task, ok := t.(*Task)
		if ok {
			go task.job()
			if !task.isCycle {
				iter_tmp := iter
				iter = iter.Prev()
				tt.taskQueue.Remove(iter_tmp)
				if iter == nil {
					return
				}
			}
		}
	}
}

// SetTimeOut 设定超时机制，当设定此函数后，定时器会从任务启动时间开始计时，
//如果达到此时间后，任务队列中的任务达仍然未被执行完，则中止中剩余的任务，并发出警告
func (tt *TimeTicker) SetTimeOut(setTime time.Duration) {

}
